#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <cstdlib>
#include <cassert>
#include <ctime>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
#define MakeSeed() srand((unsigned long)time(nullptr))
#define PROCSS_NUM 10
///////////////////////////////////////子进程要完成的某种任务 -- 模拟一下/////////////////////////
// 函数指针 类型
typedef void (*func_t)();

void downLoadTask()
{
    std::cout << getpid() << ": 下载任务"
              << std::endl;
    sleep(1);
}

void ioTask()
{
    std::cout << getpid() << ": IO任务"
              << std::endl;
    sleep(1);
}

void flushTask()
{
    std::cout << getpid() << ": 刷新任务"
              << std::endl;
    sleep(1);
}

void loadTaskFunc(std::vector<func_t> *out)
{
    assert(out != nullptr);
    out->push_back(downLoadTask);
    out->push_back(ioTask);
    out->push_back(flushTask);
}

/////////////////////////////////////////////////下面的代码是一个多进程程序//////////////////////
class subEp // Endpoint
{
public:
    subEp(pid_t subId, int writeFd)
        : _subId(subId), _writeFd(writeFd)
    {
        char nameBuffer[1024];
        snprintf(nameBuffer, sizeof nameBuffer, "process%d:[pid(%d)-fd(%d)]\n", _num++, _subId, _writeFd);
        _name = nameBuffer;
    }

public:
    static int _num;
    std::string _name;
    pid_t _subId;
    int _writeFd;
};
int subEp::_num = 0;

int sendTask(const subEp &subs, int commandCode)
{
    cout << "sendTask:" << subs._name;
    int ret = write(subs._writeFd, &commandCode, sizeof(int));
    assert(ret == sizeof(int));
}
int recvTask(int readId)
{
    int commandCode = 0;
    int ret = read(readId, &commandCode, sizeof(int));
    if (ret == 4)
    {
        return commandCode;
    }
    else if (ret <= 0)
        return -1;
    else
        return 0;
}
void createProc(vector<subEp> &subs, vector<func_t> &func)
{
    for (int i = 0; i < PROCSS_NUM; ++i)
    {
        int pipeFd[2] = {0};
        int ret = pipe(pipeFd);
        if (ret == -1)
        {
            cerr << "createProc:" << strerror(errno) << endl;
            exit(1);
        }
        pid_t id = fork();
        if (id == 0)
        {
            while (true)
            {
                close(pipeFd[1]);
                int commandCode = recvTask(pipeFd[0]);
                if (commandCode >= 0 && commandCode < func.size())
                {
                    func[commandCode]();
                }
                else
                    break;
            }
            exit(0);
        }
        close(pipeFd[0]);
        subs.push_back(subEp(id, pipeFd[1]));
    }
}
void loadBlanceContrl(vector<subEp> &subs, vector<func_t> &func, int count)
{
    MakeSeed();
    int procNum = subs.size();
    int taskNum = func.size();
    bool forever = count == 0 ? true : false;
    while (true)
    {
        int procId = rand() % procNum;
        int taskId = rand() % taskNum;
        sendTask(subs[procId], taskId);
        sleep(1);
        if (!forever)
        {
            count--;
            if (count == 0)
                break;
        }
    }
    for (int i = 0; i < procNum; i++)
        close(subs[i]._writeFd);
}
void waitProc(const vector<subEp> &subs)
{
    for (int i = 0; i < PROCSS_NUM; ++i)
    {
        waitpid(subs[i]._subId, nullptr, 0);
        cout << "waitProc successs[" << i << "]:" << subs[i]._subId << endl;
    }
}
int main()
{
    // 装载任务
    vector<subEp> subs;
    vector<func_t> func;
    loadTaskFunc(&func);

    // 创建进程
    createProc(subs, func);

    // 分配任务
    loadBlanceContrl(subs, func, 10);

    // 回收进程
    waitProc(subs);
    return 0;
}